package com.hqd.jjvm.rtda;

import com.hqd.jjvm.rtda.heap.JMethod;
import com.hqd.jjvm.rtda.obj.JObject;
import lombok.Getter;

import java.util.Stack;

/**
 * 虚拟机栈
 */
@Getter
public class JvmStack extends Stack<StackFrame> {
    private Integer maxStackSize;
    private Integer maxLocalSize;
    private StackFrame top;

    public JvmStack(JMethod jMethod) {
        this.maxStackSize = jMethod.getMaxStack();
        this.maxLocalSize = jMethod.getMaxLocals();
        this.top = new StackFrame(jMethod);
        this.push(top);
    }


    public Integer getLocalVarsIntVal(int index) {
        return this.getTop().getLocalVars().getIntVal(index);
    }

    public Float getLocalVarsFloatVal(int index) {
        return this.getTop().getLocalVars().getFloatVal(index);
    }

    public void setLocalVarsIntVal(int index, int val) {
        this.getTop().getLocalVars().setIntVal(index, val);
    }

    public void setLocalVarsFloatVal(int index, float val) {
        this.getTop().getLocalVars().setFloatVal(index, val);
    }

    public void setLocalVarsLongVal(int index, long val) {
        this.getTop().getLocalVars().setLongVal(index, val);
    }

    public void setLocalVarsDoubleVal(int index, double val) {
        this.getTop().getLocalVars().setDoubleVal(index, val);
    }

    public void setLocalVarsRefVal(int index, JObject val) {
        this.getTop().getLocalVars().setRefVal(index, val);
    }

    public Integer popOperandStackIntVal() {
        return this.getTop().getOperandStack().popInt();
    }

    public Float popOperandStackFloatVal() {
        return this.getTop().getOperandStack().popFloat();
    }

    public Double popOperandStackDoubleVal() {
        return this.getTop().getOperandStack().popDouble();
    }

    public Long popOperandStackLongVal() {
        return this.getTop().getOperandStack().popLong();
    }

    public JObject popOperandStackRefVal() {
        return this.getTop().getOperandStack().popRef();
    }

    public Object popOperandStackVal() {
        return this.getTop().getOperandStack().popVal();
    }

    public void pushOperandStackIntVal(Integer val) {
        this.getTop().getOperandStack().pushInt(val);
    }

    public void pushOperandStackBoolVal(boolean val) {
        this.getTop().getOperandStack().pushInt(val ? 1 : 0);
    }

    public void pushOperandStackRefVal(JObject val) {
        this.getTop().getOperandStack().pushRef(val);
    }

    public void pushOperandStackFloatVal(Float val) {
        this.getTop().getOperandStack().pushFloat(val);
    }

    public Long getLocalVarsLongVal(Integer index) {
        return this.getTop().getLocalVars().getLongVal(index);
    }

    public Integer getLocalVarsIntVal(Integer index) {
        return this.getTop().getLocalVars().getIntVal(index);
    }

    public Double getLocalVarsDoubleVal(Integer index) {
        return this.getTop().getLocalVars().getDoubleVal(index);
    }

    public Float getLocalVarsFloatVal(Integer index) {
        return this.getTop().getLocalVars().getFloatVal(index);
    }

    public JObject getLocalVarsRefVal(Integer index) {
        return this.getTop().getLocalVars().getRefVal(index);
    }


    public void pushOperandStackLongVal(Long val) {
        this.getTop().getOperandStack().pushLong(val);
    }


    public void pushOperandStackDoubleVal(Double val) {
        this.getTop().getOperandStack().pushDouble(val);
    }


    public StackFrame getTop() {
        return this.peek();
    }
}
